//
// Interpret.cpp for  in /home/lund/Projets/abstract-vm/vmtmp
// 
// Made by florian dewulf
// Login   <dewulf_f@epitech.net>
// 
// Started on  Mon Feb 18 11:02:55 2013 florian dewulf
// Last update Tue Feb 19 20:09:50 2013 florian dewulf
//

#include	"Interpret.hpp"

Interpret::Interpret(const bool &input) : _str(""), _state(input)
{
  this->epur_op();
}

Interpret::~Interpret()
{
}

//static
void		Interpret::trunc_str(std::string &str)
{
  str = str.substr(0, str.find(";"));
}

//static
std::string	Interpret::epur_space(const std::string &str)
{
  std::string	line;

  for (unsigned int i = 0 ; i < str.size() ; ++i) {
    if (str[i] == ' ' || str[i] == '\t') {
      if (i != 0) {
	i++;
      }
      while (i < str.size() && (str[i] == ' ' || str[i] == '\t'))
	i++;
      if (i != str.size())
	line += ' ';
      i--;
    }
    else {
      line += str[i];
    }
  }
  return (line);
}

/*
** is_ functions :
*/

bool		Interpret::is_end() const
{
  if (this->_str.find(";;") != std::string::npos && this->_state)
    return (true);
  return (false);
}

bool		Interpret::is_op() const
{
  unsigned int	pos = -1;

  if (((pos = this->_str.find("add")) != std::string::npos && pos == 0) ||
      ((pos = this->_str.find("sub")) != std::string::npos && pos == 0) ||
      ((pos = this->_str.find("mul")) != std::string::npos && pos == 0) ||
      ((pos = this->_str.find("div")) != std::string::npos && pos == 0) ||
      ((pos = this->_str.find("mod")) != std::string::npos && pos == 0))
    return true;
  return false;
}

/* -- Generic function for `cmd type(value)` -- */

static bool	is_2_arg(const std::string &str, const std::string commande)
{
  unsigned int	pos;

  if ((pos = str.find(commande)) != std::string::npos && pos == 0 &&
      ((pos = str.find(" int8(")) != std::string::npos ||
       (pos = str.find(" int16(")) != std::string::npos ||
       (pos = str.find(" int32(")) != std::string::npos ||
       (pos = str.find(" float(")) != std::string::npos ||
       (pos = str.find(" double(")) != std::string::npos) &&
       str.find(")") == str.size() - 1)
    return true;
  return false;
}

bool		Interpret::is_push() const
{
  return (is_2_arg(this->_str, "push"));
}

bool		Interpret::is_assert() const
{
  return (is_2_arg(this->_str, "assert"));
}

/* -- Generic function for `cmd` -- */

static bool	is_1_arg(const std::string &str, const std::string &commande)
{
  unsigned int	pos;

  if ((pos = str.find(commande)) != std::string::npos && pos == 0 &&
      commande.size() == str.size())
    return true;
  return false;
}

bool		Interpret::is_pop() const
{	return (is_1_arg(this->_str, "pop"));	}

bool		Interpret::is_dump() const
{	return (is_1_arg(this->_str, "dump"));	}

bool		Interpret::is_print() const
{	return (is_1_arg(this->_str, "print"));	}

bool		Interpret::is_exit() const
{	return (is_1_arg(this->_str, "exit"));	}

/* ---------------- */

/*template<class T>
T		Interpret::getNb_int() const
{
  std::this->_string	nb;

  nb = this->_str.substr(this->_str.find("("),
		  this->_str.find(")") - this->_str.find("("));
  return (static_cast<T>(atoi(nb.c_str())));
}

template<class T>
T		Interpret::getNb_dec() const
{
  std::this->_string	nb;

  nb = this->_str.substr(this->_str.find("("),
		  this->_str.find(")") - this->_str.find("("));
  return (static_cast<T>(atof(nb.c_str())));
  }
*/

Interpret::Type	Interpret::getType() const
{
  for (unsigned int offset = this->_str.find("(") + 1 ;
       this->_str[offset] != ')' && offset != this->_str.size() ; ++offset) {
    if (this->_str[offset] == '.')
      return (Interpret::DEC);
  }
  return (Interpret::INT);
}

static bool	search_char(char c)
{
  std::string	str("0123456789.+-");

  for (unsigned int curs = 0 ; curs < str.size() ; ++curs)
    if (str[curs] == c)
      return true;
  return false;
}

bool		Interpret::check_validity() const
{
  for (unsigned int offset = this->_str.find("(") + 1;
       this->_str[offset] != ')' && offset != this->_str.size() ; ++offset) {
    if (this->_str[offset] == '+' || this->_str[offset] == '-' &&
	offset != this->_str.find("(") + 1)
      return false;
    else if (!search_char(this->_str[offset]))
      return false;
  }
  return true;
}

bool		Interpret::epur_op()
{
  unsigned int	pos;
  bool		op = true;		//true = +, false = -

  if ((pos = this->_str.find("(")) != std::string::npos &&
      this->_str.find("+") == std::string::npos &&
      this->_str.find("-") == std::string::npos)
    return true;
  if (pos == std::string::npos)
    return false;
  for (pos += 1 ; pos < this->_str.size() && (this->_str[pos] == '+' || this->_str[pos] == '-') ; ++pos) {
    if (this->_str[pos] == '-')
      op = !op;
  }
  if (op)
    this->_str.replace(this->_str.find("(") + 1, pos - (this->_str.find("(") + 1), "");
  else
    this->_str.replace(this->_str.find("(") + 1, pos - (this->_str.find("(") + 1), "-");
  return (true);
}

void		Interpret::setStr(const std::string &str)
{
  this->_str = str;
}

std::string	Interpret::getStr() const
{
  return (this->_str);
}
